#include <ResourceManager.h>
#include <ProcessManager.h>
#include <Filesystem.h>
#include <SharedObject.h>

ResourceManager::ResourceManager()
  : names(&ResourceNameMap::stringEqPredicate, &ResourceNameMap::stringHashFunction)
{
  nextId = 1;
  resource = new Resource((Callable*)this, "ResourceManager");
  resource->add((Resource::Call0)&ResourceManager::mkfs, ResourceManager_IF::mkfs);
  resource->add((Resource::Call1)&ResourceManager::mkbuf, ResourceManager_IF::mkbuf);
  resource->add((Resource::Call2)&ResourceManager::share, ResourceManager_IF::share);
  resource->add((Resource::Call3)&ResourceManager::unshare, ResourceManager_IF::unshare);
  resource->add((Resource::Call1)&ResourceManager::freebuf, ResourceManager_IF::freebuf);
}

ResourceManager::~ResourceManager()
{
}

u32int ResourceManager::create(Resource *r, const char *name)
{
  r->setId(nextId);
  resources.add(nextId, r);
  if (name)
    names.add((char*)name, r);
  return nextId++;
}

u32int ResourceManager::mkfs()
{
  Filesystem *fs = new Filesystem(NULL, NULL);
  return fs->resource->getId();
}

Resource *ResourceManager::request(u32int id)
{
  return resources.lookup(id);
}

Resource *ResourceManager::request(const char *name)
{
  if (!strcmp((char*)name, (char*)"Filesystem"))
    return filesystem->resource;
  return names.lookup((char*)name);
}

void ResourceManager::destroy(u32int id)
{
  Resource *r = resources.remove(id);
  if (!r)
    return;
  for (int i = 0; i < names.length(); i++)
  {
    if(names.getByIndex(i) == r)
    {
      names.remove(names.getKeyByIndex(i));
      break;
    }
  }
}

u32int ResourceManager::mkbuf(Address len)
{
  SharedObject *so = new SharedObject(len);
  return so->resource->getId();
}

void ResourceManager::freebuf(u32int so)
{
  SharedObject *obj = (SharedObject*)resourceManager.request(so)->getTarget();
  delete obj;
}

void *ResourceManager::share(void *ptr, u32int len)
{
  DEBUG_MSG("ResourceManager::share(" << hex << (u32int)ptr << ", " << len << ").");
  void *buf = memoryManager.umalloc(len);
  if (ptr)
    Kernel::memcpy((u8int*)buf, (u8int*)ptr, len);
  return buf;
}

u32int ResourceManager::unshare(void *buf, void *ptr, u32int len)
{
  if (ptr)
    Kernel::memcpy((u8int*)ptr, (u8int*)buf, len);
  memoryManager.ufree(buf);
  return 0;
}
